﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Browser;
using System.Windows.Media.Animation;
using System.Diagnostics;
using System.Windows.Threading;

namespace WorkflowDesigner.Workflow
{
    /// <summary>
    /// 各种形状的类型，追加类型的时候这里需要追加一个枚举
    /// </summary>
    public enum FlowItemType
    {
        Unknown = 0,
        Start,
        Normal,
        End,
        Condition,
        Beeline
    }

    public delegate void ControlMoveNotify(WorkflowBase node);
    public delegate void ControlDeleteNotify(WorkflowBase node);

    /// <summary>
    /// 所有的类型都从这里继承
    /// </summary>
    public abstract class WorkflowBase : UserControl
    {
        // 移动消息,供线条使用,移动的时候线条可能也需要跟着走
        public ControlMoveNotify OnControlMove = null;
        // 删除消息,供线条使用,线条需要知道控件是否已经删除
        public ControlDeleteNotify OnControlDelete = null;

        // 判断鼠标左键是否按下
        protected bool m_isMouseDown = false;
        // 相对于本窗口的坐标
        protected Point m_ptOffset = new Point();
        // 双击事件检测器
        protected DispatcherTimer m_doubleClickTimer = null;

        protected virtual void OnInit()
        {
            Size sizeReal = WorkflowBase.GetRealSize(this.ItemType);
            this.Width = sizeReal.Width;
            this.Height = sizeReal.Height;
            m_doubleClickTimer = new System.Windows.Threading.DispatcherTimer();
            m_doubleClickTimer.Interval = new TimeSpan(0, 0, 0, 0, 200);
            m_doubleClickTimer.Tick += new EventHandler(DoubleClick_Timer);
        }

        public virtual FlowItemType ItemType
        {
            get
            {
                return FlowItemType.Unknown;
            }
        }

        protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
        {
            base.OnMouseLeftButtonDown(e);
            Debug.WriteLine("Node_OnMouseLeftButtonDown");
            if (IsUseForToolBox)
            {
                return;
            }
            //e.Handled = true;
            this.IsFocus = true;
            this.Cursor = Cursors.Hand;
            // 检测双击处理
            if (m_doubleClickTimer.IsEnabled)
            {
                // 能走到这里，说明上一次的时间轴没有完成
                // 换句话说就是，在200毫秒之内，现在至少是第二次鼠标按下
                // 现在可以认为是鼠标双击！
                m_doubleClickTimer.Stop();
                // TODO: 进行双击处理
                OnDoubleClick();
            }
            else
            {
                // 开始时间轴处理，以200毫秒为期限
                m_doubleClickTimer.Start();
                m_isMouseDown = true;
                m_ptOffset = e.GetPosition(this);
                this.CaptureMouse();
            }
        }

        protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
        {
            base.OnMouseLeftButtonUp(e);
            if (IsUseForToolBox)
            {
                return;
            }
            if (m_isMouseDown)
            {
                e.Handled = true;
                m_isMouseDown = false;
                this.Cursor = Cursors.Arrow;
                this.ReleaseMouseCapture();
                this.IsFocus = true;
                //App.theMainView.ShowGridLine(App.theMainView.IsGridLineShow);
            }
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);
            if (IsUseForToolBox)
            {
                return;
            }
            if (m_isMouseDown)
            {
                this.Cursor = Cursors.Hand;
                Point newPosition = e.GetPosition((UIElement)this.Parent);
                this.MoveTo(newPosition.X - m_ptOffset.X, newPosition.Y - m_ptOffset.Y);
                App.theMainView.TryResize();
                if (this.OnControlMove != null)
                {
                    this.OnControlMove(this);
                }
            }
        }

        protected virtual void OnDoubleClick()
        {
            // 进行双击处理
            MessageBox.Show("[节点] 双击处理");
        }

        private void DoubleClick_Timer(object sender, EventArgs e)
        {
            // 时间轴处理，以200毫秒为期限
            // 200毫秒之后自动停止
            // 下一次鼠标按下的时候会重新开始计时
            m_doubleClickTimer.Stop();
        }

        protected bool m_isFocus = false;

        public virtual bool IsFocus
        {
            get
            {
                return m_isFocus;
            }
            set
            {
                m_isFocus = value;
            }
        }

        protected bool m_isUseForToolBox = false;

        public virtual bool IsUseForToolBox
        {
            get
            {
                return m_isUseForToolBox;
            }
            set
            {
                m_isUseForToolBox = value;
            }
        }

        /// <summary>
        /// 中心位置
        /// </summary>
        public virtual Point CenterPoint
        {
            get
            {
                Point ptLocation = this.Location;
                Size sizeRealSize = GetRealSize(this.ItemType);
                double dX = ptLocation.X + sizeRealSize.Width * m_dZoom / 2.0;
                double dY = ptLocation.Y + sizeRealSize.Height * m_dZoom / 2.0;
                return new Point(dX, dY);
            }
        }

        /// <summary>
        /// 得到左上角坐标
        /// </summary>
        public virtual Point Location
        {
            get
            {
                double dTop = (double)this.GetValue(Canvas.TopProperty);
                double dLeft = (double)this.GetValue(Canvas.LeftProperty);
                return new Point(dLeft, dTop);
            }
        }

        /// <summary>
        /// 真实大小，也就是默认大小乘以缩放比例的结果
        /// </summary>
        public virtual Size RealSize
        {
            get
            {
                Size sizeRealSize = GetRealSize(this.ItemType);
                double dWidth = sizeRealSize.Width * m_dZoom;
                double dHeight = sizeRealSize.Height * m_dZoom;
                return new Size(dWidth, dHeight);
            }
        }

        private double m_dZoom = 1.0;

        /// <summary>
        /// 工作区的缩放比例，默认为1.0，也就是没有缩放
        /// </summary>
        /// <param name="fZoom"></param>
        [ScriptableMember]
        public virtual double Zoom
        {
            get
            {
                return m_dZoom;
            }
            set
            {
                m_dZoom = value;
                Size seRealSize = RealSize;
                this.Width = seRealSize.Width;
                this.Height = seRealSize.Height;
            }
        }

        /// <summary>
        /// 形状外面有一个点，从本控件中心 CenterPoint 到 ptOuterPoint 连线
        /// 连接点如果和Border有交点，求出该点的坐标
        /// 如果没有交点则表示ptOuterPoint在本控件内部，返回CenterPoint即可
        /// </summary>
        /// <param name="ptOuterPoint">给定点的坐标</param>
        /// <returns>交点的坐标</returns>
        public virtual Point GetCrossPoint(Point ptOuterPoint)
        {
            return this.CenterPoint;
        }

        #region 关闭时启用动画，慢慢消失
        public virtual void OnDelete()
        {
            isDeleted = true;
            // 创建故事板
            Storyboard sbDelete = new Storyboard();
            // 创建double属性的动画
            DoubleAnimation doubleAni = new DoubleAnimation();
            doubleAni.From = 1.0;
            doubleAni.To = 0.0;
            // 0.7秒之内从可见到不可见过渡
            doubleAni.Duration = TimeSpan.FromSeconds(0.7);
            // 设置故事板(目标：透明度)
            Storyboard.SetTargetProperty(doubleAni, new PropertyPath("Opacity"));
            sbDelete.Children.Add(doubleAni);
            // Set target for storyboard
            Storyboard.SetTarget(sbDelete, this);
            // Begin storyboard
            sbDelete.Completed += new EventHandler(sbDelete_Completed);
            sbDelete.Begin();
            // 通知其他控件自己被删除了
            if (OnControlDelete != null)
            {
                OnControlDelete(this);
            }
        }

        protected virtual void sbDelete_Completed(object sender, EventArgs e)
        {
            App.theMainView.DeleteFlowItem(this);
        }

        private bool isDeleted = false;

        public bool IsDeleted
        {
            get
            {
                return isDeleted;
            }
        }
        #endregion

        public virtual void MoveTo(double dLeft, double dTop)
        {
            if (dTop >= 0.0)
            {
                this.SetValue(Canvas.TopProperty, dTop);
            }
            if (dLeft >= 0.0)
            {
                this.SetValue(Canvas.LeftProperty, dLeft);
            }
            // 通知其他控件自己被移动了
            if (OnControlMove != null)
            {
                OnControlMove(this);
            }
        }

        public virtual void ResizeTo(double dWidth, double dHeight)
        {
            this.Width = dWidth;
            this.Height = dHeight;
        }

        public virtual void BringToTop()
        {
            this.SetValue(Canvas.ZIndexProperty, App.NextMaxIndex);
        }

        /// <summary>
        /// 这里是各种形状的默认大小
        /// 如果界面有缩放，可以使用默认大小乘以缩放比例得到运行时的大小
        /// 默认缩放比例为 1.0, 也就是不缩放
        /// </summary>
        /// <param name="itemType"></param>
        /// <returns></returns>
        public static Size GetRealSize(FlowItemType itemType)
        {
            Size sizeReal = new Size();
            switch (itemType)
            {
                case FlowItemType.Condition:
                    sizeReal.Width = 120.0;
                    sizeReal.Height = 70.0;
                    break;
                case FlowItemType.Start:
                    sizeReal.Width = 50.0;
                    sizeReal.Height = 50.0;
                    break;
                case FlowItemType.End:
                    sizeReal.Width = 50.0;
                    sizeReal.Height = 50.0;
                    break;
                case FlowItemType.Normal:
                    sizeReal.Width = 100.0;
                    sizeReal.Height = 66.0;
                    break;
                default:
                    break;
            }
            return sizeReal;
        }

        private bool m_isMouseOver = false;

        public bool IsMouseOver
        {
            get
            {
                return m_isMouseOver;
            }
            set
            {
                m_isMouseOver = value;
            }
        }

        protected override void OnMouseEnter(MouseEventArgs e)
        {
            m_isMouseOver = true;
            base.OnMouseEnter(e);
        }

        protected override void OnMouseLeave(MouseEventArgs e)
        {
            m_isMouseOver = false;
            base.OnMouseLeave(e);
        }

        #region 供外观设置用的所有函数

        public virtual void SetFontBold()
        {
        }

        public virtual void SetFontItalics()
        {
        }

        public virtual void SetFontUnderline()
        {
        }

        public virtual void SetFontSize(double dFontSize)
        {
        }

        public virtual void SetFontName(string strFontName)
        {
        }

        public virtual void SetFontColor(Color clrFont)
        {
        }

        public virtual void SetFillColor(Color clrFill)
        {
        }

        public virtual void SetBorderLineStyle(Color clrBorder, double dBorderWidth)
        {
        }

        public virtual void SetShadowStyle(Color clrShadow, Thickness offset)
        {
        }

        [ScriptableMember]
        public virtual void SetFontColor(string clrFont)
        {
            Color clr = Utility.GetColor(clrFont);
            SetFontColor(clr);
        }

        [ScriptableMember]
        public virtual void SetFillColor(string clrFill)
        {
            Color clr = Utility.GetColor(clrFill);
            SetFillColor(clr);
        }

        [ScriptableMember]
        public virtual void SetBorderLineStyle(string clrBorder, double dBorderWidth)
        {
            Color clr = Utility.GetColor(clrBorder);
            SetBorderLineStyle(clr, dBorderWidth);
        }

        [ScriptableMember]
        public virtual void SetShadowStyle(string clrShadow, Thickness offset)
        {
            Color clr = Utility.GetColor(clrShadow);
            SetShadowStyle(clr, offset);
        }

        #endregion
    }
}
